package indi.juzhuohan.chatroom.server;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JTextPane;

import indi.juzhuohan.chatroom.entity.ChatStatus;
import indi.juzhuohan.chatroom.entity.FontStyle;
import indi.juzhuohan.chatroom.entity.TransferInfo;
import indi.juzhuohan.chatroom.io.IOStream;
import indi.juzhuohan.chatroom.util.FontSupport;

/**
 * 服务器端开辟套接字长链接线程
 * 
 * @author 鞠卓瀚
 *
 */
public class ServerHandler extends Thread {

	Socket socket;
	Serverframe serverframe;

	public static String Userfile = "G:\\java\\chatroom_socket\\src\\user.txt";

	public ServerHandler(Socket socket, Serverframe serverframe) {
		this.socket = socket;
		this.serverframe = serverframe;
	}

//	静态保证在同一表，而不是一个进程一个表
	static List<String> onlineUsers = new ArrayList<>();
	static List<Socket> onlineSockets = new ArrayList<>();

	/**
	 * 服务器一直保持无限循环拿消息
	 */
	@Override
	public void run() {
		while (true) {
			try {
//				读取socket
				Object obj = IOStream.readMessage(socket);
//				分辨类别
				if (obj instanceof TransferInfo) {
//					强制转换
					TransferInfo tfi = (TransferInfo) obj;
					if (tfi.getStatusEnum() == ChatStatus.LOGIN) {
//						登录消息
						loginHandler(tfi);
					} else if (tfi.getStatusEnum() == ChatStatus.CHAT) {
//						聊天消息
						chatHandler(tfi);
					} else if (tfi.getStatusEnum() == ChatStatus.DD) {
//						抖动消息
						Jitter(tfi);
					} else if (tfi.getStatusEnum() == ChatStatus.QUIT) {
//						退出处理
						loginOut(tfi);

//						休眠1秒后
						Thread.sleep(1000);
//						关闭当前socket
						socket.close();
//						关闭当前线程
						this.interrupt();
//						跳出循环
						break;
					}
				}
				Thread.sleep(1000);
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null, "对方离线", "发送失败", JOptionPane.WARNING_MESSAGE);
			}
		}
	}

	/**
	 * 检验账号密码功能，默认FALSE
	 * 
	 * @param tfi
	 * @return
	 */
	public boolean checkUserLogin(TransferInfo tfi) {
		try {
			String userName = tfi.getUserName();
			String password = tfi.getPassword();
//			FileIO流 读文件
			FileInputStream fis = new FileInputStream(new File(Userfile));
			DataInputStream dis = new DataInputStream(fis);
			String row = null;
			while ((row = dis.readLine()) != null) {
//				从文件中读取的行
				if ((userName + "|" + password).equals(row)) {
					return true;
				}
			}
		} catch (IOException e) {
			System.out.println("serverhandler2");
		}
		return false;
	}

	/**
	 * 检验账号密码功能，默认FALSE
	 * 
	 * @param tfi
	 */
	private void loginHandler(TransferInfo tfi) {
//		检验账号密码是否正确
		boolean flag = checkUserLogin(tfi);
//		初始化tfi登录状态为false
		tfi.setLoginSucceessFlag(false);
		if (flag) {

//			返回登录成功给客户端
			tfi.setLoginSucceessFlag(true);
			tfi.setStatusEnum(ChatStatus.LOGIN);
			IOStream.writeMessage(socket, tfi);

//			获取账户名
			String userName = tfi.getUserName();

//			获取登录的账户和socket添加list中
			onlineUsers.add(userName);
			onlineSockets.add(socket);

//			在线用户和管道的对应关系
			ChatServer.userSocketMap.put(userName, socket);

//			发系统消息给在线客户端，该用户已上线
			tfi = new TransferInfo();
			tfi.setStatusEnum(ChatStatus.NOTICE);
			String notice = " >>> 用户<" + userName + "> 上线啦";
			tfi.setNotice(notice);
			sendAll(tfi);

//			准备最新用户列表给当前客户端
			tfi = new TransferInfo();
			tfi.setUserOnlineArray(onlineUsers.toArray(new String[onlineUsers.size()]));
			tfi.setStatusEnum(ChatStatus.ULIST);
			sendAll(tfi);

			flushOnlineUserList();
//			记录日志
			log(notice);

		} else {
//			返回登录失败给客户端
			IOStream.writeMessage(socket, tfi);
			log(tfi.getUserName() + "登陆失败");
		}
	}

	/**
	 * 处理客户聊天请求
	 * 
	 * @param tfi
	 */
	private void chatHandler(TransferInfo tfi) {
//		转发给其他用户
		String reciver = tfi.getReciver();
		if ("所有人".equals(reciver)) {
//			发送给所有人
			sendAll(tfi);
//			记录日志
			List<FontStyle> contents = tfi.getContent();
			FontSupport.logfontDecode(serverframe.serverUI.txtLog, contents, tfi.getSender(), "所有人");
		} else {
//			私聊
			send(tfi);
			List<FontStyle> contents = tfi.getContent();
			FontSupport.logfontDecode(serverframe.serverUI.txtLog, contents, tfi.getSender(), tfi.getReciver());
		}
	}

	/***
	 * 发送消息-给所有人-操作
	 * 
	 * @param tfi
	 */
	public void sendAll(TransferInfo tfi) {
//		循环在线socket列表依次写出去
		for (int i = 0; i < onlineSockets.size(); i++) {
			Socket tempSocket = onlineSockets.get(i);
			IOStream.writeMessage(tempSocket, tfi);
		}
	}

	/**
	 * 刷新服务器的用户列表
	 */
	public void flushOnlineUserList() {
//		获取服务器的列表
		JList lstUser = serverframe.onlineuserpanel.lstUser;
//		集合转成string数组
		String[] userArray = onlineUsers.toArray(new String[onlineUsers.size()]);
//		放进数组
		lstUser.setListData(userArray);

		serverframe.serverUI.txtNumber.setText(onlineUsers.size() + " 人");
		serverframe.onlineuserpanel.txtNumber.setText(onlineUsers.size() + " 人");
	}

	/**
	 * 抖动消息给所有人
	 * 
	 * @param tfi
	 */
	private void Jitter(TransferInfo tfi) {
//		转发给其他用户
		String reciver = tfi.getReciver();
		if ("所有人".equals(reciver)) {
//			发送给所有人
			tfi.setStatusEnum(ChatStatus.DD);
			sendAll(tfi);

			tfi.setStatusEnum(ChatStatus.NOTICE);
			String notice = " >>> " + tfi.getSender() + "发送了一个抖动";
			tfi.setNotice(notice);
			sendAll(tfi);

//			记录日志
			log(" >>> 用户<" + tfi.getSender() + "> 对<所有人>发抖动");
		} else {
//			私聊
			tfi.setStatusEnum(ChatStatus.DD);
			send(tfi);

			tfi.setStatusEnum(ChatStatus.NOTICE);
			String notice = " >>> 用户<" + tfi.getSender() + ">给<" + tfi.getReciver() + ">发送了一个抖动";
			tfi.setNotice(notice);
			send(tfi);
//			记录日志
			log(" >>> 用户<" + tfi.getSender() + "> 对<" + tfi.getReciver() + ">发抖动");
		}
	}

	/**
	 * 记录日志的方法
	 * 
	 * @param log
	 */
	private void log(String log) {
		Date date = new Date();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String dateString = sdf.format(date);
		JTextPane jTextPane = serverframe.serverUI.txtLog;
		String oldlog = jTextPane.getText();
		jTextPane.setText(oldlog + "\n" + dateString + " " + log);
	}

	/**
	 * 用户退出处理，清理在线人数，刷新用户列表，告诉所有人，你已经离开
	 * 
	 * @param tfi
	 */
	private void loginOut(TransferInfo tfi) {

		String userName = tfi.getUserName();
//		将该用户从用户集合移除
		Iterator<String> userIter = onlineUsers.iterator();
		while (userIter.hasNext()) {
			if (userIter.next().equals(userName)) {
				userIter.remove();
			}
		}

//		将该用户从socket集合移除
		Iterator<Socket> socketIter = onlineSockets.iterator();
		while (socketIter.hasNext()) {
			Socket next = socketIter.next();
			if (socket == next) {
				socketIter.remove();
			}
		}

		// 将user与Socket的关系从Map中移除
		ChatServer.userSocketMap.remove(userName);

		// 刷新服务器面板的用户列表
		flushOnlineUserList();

		// 给所有在线的用户发送下线消息
		tfi.setStatusEnum(ChatStatus.NOTICE);
		sendAll(tfi);

//		记录日志
		log(" >>> 用户<" + userName + "> 离开聊天室");

		// 告诉其他人刷新用户列表
		tfi.setUserOnlineArray(onlineUsers.toArray(new String[onlineUsers.size()]));
		tfi.setStatusEnum(ChatStatus.ULIST);
		sendAll(tfi);
	}

	public void send(TransferInfo tfi) {
		String reciver = tfi.getReciver();
		String sender = tfi.getSender();
		// 根据reivcer拿到Socket管道
		// 通过用户名为键，管道为值取做map
		Socket socket1 = ChatServer.userSocketMap.get(reciver);
		IOStream.writeMessage(socket1, tfi);

		Socket socket2 = ChatServer.userSocketMap.get(sender);
		IOStream.writeMessage(socket2, tfi);
	}
}
